﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using System.IO;
using Legend.IO;
using System.Diagnostics;

namespace Legend.Core.Tests.IO.StreamExtensionsTests
{
    [TestFixture]
    public class ReadToEnd
    {
        [Test, ExpectedException(typeof(ArgumentNullException))]
        public void should_throw_exception_when_stream_is_null()
        {
            ((Stream)null).ReadToEnd(128);            
        }

        [Test]
        public void should_read_all_bytes_when_position_is_at_start_of_stream()
        {
            byte[] bytes = {1, 2, 3};
            byte[] result = null;

            using (var s = new MemoryStream(bytes))
            {
                result = s.ReadToEnd(128);    
            }

            Assert.AreEqual(3, result.Length);
            Assert.AreEqual(1, result[0]);
            Assert.AreEqual(2, result[1]);
            Assert.AreEqual(3, result[2]);
        }

        [Test]
        public void should_read_remainder_of_stream_when_position_is_not_at_start_of_stream()
        {
            byte[] bytes = { 1, 2, 3 };
            byte[] result = null;

            using (var s = new MemoryStream(bytes))
            {
                s.Position = 1;
                result = s.ReadToEnd(128);
            }

            Assert.AreEqual(2, result.Length);
            Assert.AreEqual(2, result[0]);
            Assert.AreEqual(3, result[1]);
        }

        [Test]
        public void should_read_all_of_stream_containing_lots_of_data()
        {
            byte[] bytes = this.GenerateByteArray(1);
            byte[] streamBytes;

            using (var stream = new MemoryStream(bytes))
            {
                streamBytes = stream.ReadToEnd(128);    
            }
            
            Assert.IsTrue(bytes.SequenceEqual(streamBytes));
        }

        [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
        public void should_throw_exception_when_bufferSize_is_zero()
        {
            byte[] bytes = { 1, 2, 3 };
            
            using (var s = new MemoryStream(bytes))
            {
                s.ReadToEnd(0);
            }
        }

        [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
        public void should_throw_exception_when_bufferSize_is_less_than_zero()
        {
            byte[] bytes = { 1, 2, 3 };

            using (var s = new MemoryStream(bytes))
            {
                s.ReadToEnd(-1);
            }
        }

        private byte[] GenerateByteArray(int megaBytesSize)
        {
            byte[] result = new byte[megaBytesSize * 1000000];
            
            for (int i = 0; i < result.Length; i++)
            {
                result[i] = (byte)(i % 127);
            }

            return result;
        }        
    }
}
